home *** CD-ROM | disk | FTP | other *** search
- /*
-
- +--------------------------------------------------+
- ! !
- ! Segment Call Checking Program !
- ! !
- +--------------------------------------------------+
-
- */
-
- /*
- +--------------------------------------------------+
- ! !
- ! Include Files !
- ! !
- +--------------------------------------------------+
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <fcntl.h>
- #include <ctype.h>
- #include <dos.h>
- #include "symdefs.h"
-
- /*
- +--------------------------------------------------+
- ! !
- ! Define Declarations !
- ! !
- +--------------------------------------------------+
- */
-
- #define MAXFILES 600 /* Max. No. of Files Allowed */
- #define MAXPATH 67 /* Max. Path length */
- #define MAXREFS 800 /* Max. Proc. Refs. / Proc. */
- #define MAXSEGS 20 /* Max. number of segments */
- #define MAXOVLF 300 /* Max. files for all segments */
- /* in load statement */
- typedef struct linenode {
- char *procedure ; /* Procedure name called */
- struct linenode *nextlinenode ; /* Pointer to next procedure */
- } LINENODE , *LINENODEPTR ;
-
- typedef struct wordnode {
- char *word ; /* Procedure name */
- char *filename ; /* File name where defined */
- int linenumber ; /* Line number where defined */
- int printpage ; /* Page where printed */
- LINENODEPTR firstlinenode ; /* First procedure called */
- LINENODEPTR lastlinenode ; /* Last procedure called */
- struct wordnode *left ; /* Pointer to last word node */
- struct wordnode *right ; /* Pointer to next word node */
- } WORDNODE, *WORDNODEPTR ;
-
- typedef struct filesegs {
- char *filename ; /* filename */
- int filesegno ; /* Segment number of filename */
- struct filesegs *nextfileseg ; /* Pointer to next file seg. */
- } FILESEG, *FILESEGPTR ;
-
- typedef struct key_entry {
- int length ; /* Length of key */
- char *key ; /* Pointer to key */
- } KEYWORD , *KEYWORDPTR ;
-
- /*
- +--------------------------------------------------+
- | |
- | Global Declarations |
- | |
- +--------------------------------------------------+
- */
-
- int NoOfFileSegs = 0 ; /* Number of file segments */
- FILESEG FileSegs [MAXOVLF] = {0} ; /* List of files with segments */
- LINENODE Segments [MAXSEGS] = {0} ; /* List of procs. in segments */
- int CurrentSegment = 0 ; /* Current Segment */
-
- FILE *InputFile = NULL ;
- char InputFileName[MAXPATH] = {""} ;
- unsigned InputLineNumber = 0 ;
- char InputLine [4*MAX_INPUT] = {""} ;
- long TotalLines = 0L ;
- int eofflag = FALSE;
- int totalsymbols = 0 ;
- NSCB nscb = { 0, 0, 0 } ; /* Symbol Control Block */
-
- FILE *OutputFile = NULL ;
- int OutputLineNumber = 60 ;
- int OutputPage = 0 ;
- char OutputFileName [MAXPATH] = {""} ;
-
- long xtime = 0L ;
- char datetime [28] = {""} ;
-
- int nestlevel = 0 ; /* Indicates { nesting level */
- int maxlevel = 0 ; /* Maximum level to process */
- int nrfiles = 0 ; /* Number of files processed */
- int librarycalls = FALSE; /* Process library procs? */
- int linereferences = FALSE; /* List proc line numbers? */
- int poundsign = FALSE; /* TRUE if # directive on input */
- char filetemplate [MAXPATH] = {""} ;
- char fulltemplate [MAXPATH] = {""} ;
- char pathname [MAXPATH] = {""} ;
- char *filenames [MAXFILES] ={NULL}; /* Pointers to file names */
- char *procedure = NULL ; /* Pointer to current procedure */
- char *calledprocedure = NULL ;
- char number [11] = {0} ;
- struct find_t filespec = {""} ;
- char margin [] = { " " } ; /* Left margin for print out */
-
- int Compare () ;
- extern FILE *fopen () ;
- extern void *malloc () ;
-
- main ( )
-
- /*
- +-------------------------------------------------------+
- | |
- | This program may be used to check the segmentation |
- | structure of a program for calls which invoke a |
- | segment not in the calling heirarchy. It reads |
- | the MSC link segment directives, performs a cross- |
- | reference on all 'C' files which are invoked in |
- | the load, and then checks each procedure within |
- | each segment to insure the procedures which are |
- | called (up to a user specifiable maximum depth) |
- | are either in the segment being checked or are in |
- | the root. A trace back of calling sequences which |
- | don't meet these conditions is written to a file |
- | for inspection. |
- | |
- | This program should be compiled using the large |
- | data model (compact, large, huge) and linked |
- | with a stack size of about 32000 bytes. The large |
- | stack size is required because of the recursive |
- | procedures used. |
- | |
- | |
- | Author: Willard Gersbacher CompuServID [76117,2611] |
- | |
- +-------------------------------------------------------+
- */
-
- {
- char value [MAX_SYMBOL] ;
- char *ctime () ;
- WORDNODEPTR tree ;
- WORDNODEPTR AddToTree () ;
- LINENODEPTR lptr ;
- int done ;
- int Processing ;
- int i, max ;
-
-
- printf ( "\nCheck Segments (CHKSEG) V1.0\n\n" ) ;
-
- for ( done = 0 ; done < MAXSEGS ; done++ ) {
- Segments [done].procedure = NULL ;
- Segments [done].nextlinenode = NULL ;
- } ;
-
- if ( ! GetFileSegments () ) /* Get File Segments */
- exit (0) ;
-
- GetTraceFile () ; /* Get Trace File name */
-
- Initialize ( TRUE ) ; /* Initialize program */
-
- time ( &xtime ) ;
- strncpy ( datetime, ctime ( &xtime ), 24 ) ;
- datetime [24] = '\0' ;
-
- Processing = TRUE ;
- tree = NULL ;
-
- while ( Processing ) { /* Main processing loop */
- do {
- nscb.nextt = nscb.nextp = nscb.nextc = 0 ;
- if ( eofflag != EOF ) {
- while ( GetNextProc ( value ) ) {
- if ( nestlevel == 0 ) {
- if ((procedure = (char *)malloc(strlen(value)+1)) == NULL) {
- printf ( "Out of memory\n" ) ;
- exit ( 1 ) ;
- } ;
- strcpy ( procedure, value ) ;
- tree = AddToTree ( tree, value, InputLineNumber ) ;
- }
- else {
- tree = AddToTree ( tree, value, -1 ) ;
- addtree ( tree, procedure, value ) ;
- } ;
- } ;
- TotalLines += InputLineNumber ;
- } ;
- } while ( OpenNextFile () ) ;
- printf ( "Cross-reference complete!! " ) ;
-
- printf ("\n\nTotal number of procedures processed . %7d\n",totalsymbols);
- printf ( "Total number of lines processed . . . %7ld\n",TotalLines);
-
- do {
- printf ( "\nInclude another template?\n" ) ;
- printf ( ">>> " ) ;
- if ( FGetLine ( stdin, value, MAX_SYMBOL ) > 0 &&
- toupper (value [0]) == 'Y' ) {
- nrfiles++ ;
- Initialize ( FALSE ) ;
- }
- else if ( toupper (value[0]) == 'N' )
- Processing = FALSE ;
- } while ( toupper (value[0]) != 'Y' && toupper (value[0]) != 'N' ) ;
- } ;
-
- done = FALSE ;
- while ( ! done ) {
- printf ( "Maximum call depth to trace?\n" ) ;
- printf ( ">>> " ) ;
- FGetLine ( stdin, number, 10 ) ;
- maxlevel = atoi ( number) ;
- if ( maxlevel > 0 )
- done = TRUE ;
- } ;
-
- /* Trace down all segments looking for procedures which are
- not either in the same segment as we are currently looking at
- or in the root. */
-
- done = 0 ;
- while ( Segments [++done].procedure != NULL ) {
- printf ( "\nChecking segment number %d\n", done ) ;
- sprintf ( InputLine, " Segment Check for segment number %d", done ) ;
- printline ( "" ) ;
- printline ( InputLine ) ;
- lptr = &Segments [done] ;
- CurrentSegment = done ;
- while ( lptr != (LINENODEPTR) NULL ) {
- nestlevel = 0 ;
- printf ( "...Working on %s", lptr->procedure ) ;
- max = 32 - strlen ( lptr->procedure ) ;
- for ( i = 0 ; i < max ; i++ )
- putchar ( ' ' ) ;
- putchar ( '\r' ) ;
- checktree ( tree, tree, lptr->procedure ) ;
- lptr = lptr->nextlinenode ;
- } ;
- printf ( " " ) ;
- for ( i = 0 ; i < 32 ; i++ )
- putchar ( ' ' ) ;
- putchar ( '\r' ) ;
- } ;
-
- putc ( '\x1a', OutputFile ) ; /* Write EOF byte */
- fclose ( OutputFile ) ;
- }
-
- Initialize ( first )
-
- int first ; /* TRUE if this is first call */
-
- /*
- +--------------------------------------------------+
- ! !
- ! Initialize the CHKSEG Program !
- ! !
- +--------------------------------------------------+
- */
-
- {
- int length , FileName , i, max ;
-
- FileName = FALSE ;
- while ( ! FileName ) {
- printf ( "\nEnter template for file cross-reference.\n" ) ;
- printf ( ">>> " ) ;
- length = FGetLine ( stdin, InputLine, 40 ) ;
- if ( length > 0 )
- strcpy ( filetemplate, InputLine ) ;
- else
- continue ;
- ExpandTemplate ( filetemplate, fulltemplate, pathname ) ;
-
- /* Get the files associated with template */
-
- length = _dos_findfirst ( filetemplate, _A_NORMAL , &filespec ) ;
- if ( length != 0 )
- printf ( "Not able to retrieve anything with that template\n");
- else
- FileName = TRUE ;
- } ;
-
- InputLineNumber = 0 ;
- filenames [nrfiles] = malloc ( strlen ( filespec.name ) + 1 ) ;
- if ( filenames [nrfiles] == NULL ) {
- printf ( "Out of memory\n" ) ;
- exit ( 1 ) ;
- } ;
- strcpy ( filenames [nrfiles] , filespec.name ) ;
- strcpy ( InputFileName, pathname ) ;
- strcat ( InputFileName, filespec.name ) ;
- if ( ( InputFile = fopen ( InputFileName, "r" ) ) == NULL ) {
- printf ( "Unable to open file -> %s\n", InputFileName ) ;
- eofflag = EOF ;
- }
- else {
- SetSegmentNumber ( filenames [nrfiles] ) ;
- eofflag = FGetLine ( InputFile, InputLine, 2*MAX_INPUT ) ;
- if ( eofflag == EOF )
- printf ( "Empty input file -> %s\n", InputFileName ) ;
- else {
- printf ( "Cross-referencing file %s", InputFileName ) ;
- max = 32 - strlen ( InputFileName ) ;
- for ( i = 0 ; i < max ; i++ )
- putchar ( ' ' ) ;
- putchar ( '\r' ) ;
- } ;
- } ;
- }
-
- ExpandTemplate ( template, fulltemplate, pathname )
-
- char template [] ;
- char fulltemplate [] ;
- char pathname [] ;
-
- /*
- +--------------------------------------------------+
- | |
- | This procedure expands the template given by |
- | the user into a somewhat fuller template. The |
- | path name is also returned. |
- | |
- +--------------------------------------------------+
- */
-
- {
- int i , j ;
- int colon ;
- int dot ;
- int wild ;
-
- /* Get the files associated with template */
-
- j = i = strlen ( template ) ;
- fulltemplate [0] = '\0' ;
- getcwd ( pathname, MAXPATH ) ;
- strcat ( pathname, "\\" ) ;
-
- colon = FALSE ;
- wild = FALSE ;
- dot = FALSE ;
- while ( --i >= 0 ) {
- if ( template [i] == '\\' || template [i] == '/' ) {
- strcpy ( pathname , template ) ;
- if ( dot )
- pathname [i+1] = '\0' ;
- if ( pathname [strlen(pathname)-1] != '\\' )
- strcat ( pathname, "\\" ) ;
- strcpy ( fulltemplate , template ) ;
- if ((! wild && ! dot) ) {
- if ( j > i+1 )
- strcat ( fulltemplate, "\\" ) ;
- strcat ( fulltemplate, "*.*" ) ;
- } ;
- break ;
- }
- else if ( template [i] == ':' )
- colon = TRUE ;
- else if ( template [i] == '*' || template [i] == '?' )
- wild = TRUE ;
- else if ( template [i] == '.' )
- dot = TRUE ;
- } ;
- if ( i < 0 ) {
- if ( ! wild && ! colon ) {
- getcwd ( fulltemplate, MAXPATH ) ;
- i = strlen ( fulltemplate ) ;
- if ( fulltemplate [i-1] != '\\' )
- strcat ( fulltemplate, "\\" ) ;
- strcpy ( pathname, fulltemplate ) ;
- strcat ( fulltemplate, template ) ;
- if ( ! dot )
- strcat ( fulltemplate, ".*" ) ;
- }
- else {
- strcpy ( fulltemplate, template ) ;
- if ( colon )
- pathname [2] = '\0' ;
- if ( ! wild && ! dot )
- strcat ( fulltemplate, "*.*" ) ;
- } ;
- } ;
- strupr ( pathname ) ;
- strupr ( fulltemplate ) ;
- }
-
- GetTraceFile ()
-
- /*
- +--------------------------------------------------+
- | |
- | This procedure asks the user for the file name |
- | on which the trace file is to be written. It |
- | then opens it. |
- | |
- +--------------------------------------------------+
- */
-
- {
- int FileName ;
- int ReTry ;
- int length ;
-
- FileName = FALSE ;
- while ( ! FileName ) {
- printf ( "Enter file on which trace output is be written.\n" ) ;
- printf ( ">>> " ) ;
- length = FGetLine ( stdin, InputLine, 40 ) ;
- if ( length > 0 )
- strcpy ( OutputFileName, InputLine ) ;
- else
- continue ;
-
- ReTry = FALSE ;
- if ( ( OutputFile = fopen ( OutputFileName, "r" ) ) != NULL ) {
- fclose ( OutputFile ) ;
- printf ( "The file '%s' currently exists. ", OutputFileName ) ;
- length = 0 ;
- while ( length == 0 ) {
- printf ( "Do you want to overwrite it? \n" ) ;
- printf ( ">>> " ) ;
- length = FGetLine ( stdin, InputLine, 20 ) ;
- if ( toupper ( InputLine[0] ) != 'Y' )
- ReTry = TRUE ;
- } ;
- } ;
- if ( ReTry )
- continue ;
-
- if ( ( OutputFile = fopen ( OutputFileName, "w" ) ) == NULL )
- printf ( "Unable to open '%s'.\n", OutputFileName ) ;
- else
- FileName = TRUE ;
- } ;
- }
-
- OpenNextFile ()
-
- /*
- +--------------------------------------------------+
- | |
- | This procedure is called to open the next file |
- | based on the current file template. A return |
- | value of FALSE indicates no more files for this |
- | template. |
- | |
- +--------------------------------------------------+
- */
-
- {
- int i, max ;
-
- InputLineNumber = 0 ;
- fclose ( InputFile ) ;
- if ( nestlevel > 0 )
- printf ("Warning: Unbalanced brackets in %s\n",InputFileName) ;
- nestlevel = 0 ;
-
- while ( _dos_findnext ( &filespec ) == 0 ) {
- filenames [++nrfiles] = malloc ( strlen ( filespec.name ) + 1 ) ;
- if ( filenames [nrfiles] == NULL ) {
- printf ( "Out of memory.\n" ) ;
- exit ( 1 ) ;
- } ;
- if ( nrfiles >= MAXFILES ) {
- printf ( "Too many files.\n" ) ;
- exit ( 1 ) ;
- } ;
-
- strcpy ( filenames [nrfiles] , filespec.name ) ;
- strcpy ( InputFileName, pathname ) ;
- strcat ( InputFileName, filespec.name ) ;
- if ( ( InputFile = fopen ( InputFileName, "r" ) ) != NULL ) {
- i = FGetLine ( InputFile, InputLine, 2*MAX_INPUT ) ;
- if ( i == EOF ) {
- fclose ( InputFile ) ;
- printf ( "Empty input file -> %s\n", InputFileName ) ;
- continue ;
- }
- else {
- SetSegmentNumber ( filenames [nrfiles] ) ;
- printf ( "Cross-referencing file %s", InputFileName ) ;
- max = 32 - strlen ( InputFileName ) ;
- for ( i = 0 ; i < max ; i++ )
- putchar ( ' ' ) ;
- putchar ( '\r' ) ;
- } ;
- }
- else {
- printf ( "Unable to open file -> %s\n", InputFileName ) ;
- continue ;
- } ;
- eofflag = FALSE ;
- return ( TRUE ) ;
- } ;
- return ( FALSE ) ;
- }
-
- FGetLine ( FilePtr, Text, MaxText )
-
- FILE *FilePtr ; /* Pointer to file */
- char Text [] ; /* Read text from TTY */
- int MaxText ; /* Max. text to read */
-
- /*
- +--------------------------------------------------+
- ! !
- ! Read a line of text from file/user !
- ! !
- +--------------------------------------------------+
- */
-
- {
- int i, c, toolong ;
-
- i = 0 ;
- toolong = FALSE ;
- while ( (c=getc(FilePtr)) != EOF && c != '\n' )
- if ( i < MaxText-1 )
- Text [i++] = c ;
- else
- toolong = TRUE ;
- Text [i] = '\0' ;
- if ( c != EOF )
- InputLineNumber++ ;
- else
- i = EOF ;
- if ( toolong )
- printf ( "Error: Input record exceeds maximum - %d\n",
- MaxText-1 ) ;
- if ( Text [0] == '#' )
- poundsign = TRUE ;
- else
- poundsign = FALSE ;
- return ( i ) ;
- }
-
- GetNextProc ( symbol )
-
- char symbol[] ; /* Text of Procedure name */
-
- /*
- +--------------------------------------------------+
- | |
- | This procedure will get the next procedure name |
- | in the input stream (returned in 'symbol'). |
- | |
- | The calling format is as follows: |
- | |
- | if ( GetNextProc ( symbol ) ) ... ; |
- | |
- | A return value of TRUE indicates a proc. was |
- | found (which is returned in 'symbol'). |
- | |
- +--------------------------------------------------+
- */
-
- {
- int SymbolLength ;
- int table ;
- int parens ;
- char scratch [MAX_SYMBOL] ;
-
-
- Retry:
- SymbolLength = GetSymbol ( &nscb, InputLine, symbol, MAX_SYMBOL ) ;
-
- Retry1:
- if ( nscb.nextt == IDENTIFIER ) {
-
- if ( IsKeyword ( symbol ) )
- goto Retry ;
- if ( ! librarycalls && IsLibraryCall ( symbol ) )
- goto Retry ;
- SymbolLength = GetSymbol ( &nscb, InputLine, scratch, MAX_SYMBOL ) ;
- if ( nscb.nextt == SPECIAL && scratch [0] == '(' ) {
- if ( nestlevel == 0 ) {
- parens = 1 ;
- while ( nscb.nextt != EOS && parens > 0 ) {
- SymbolLength = GetSymbol ( &nscb, InputLine, scratch,
- MAX_SYMBOL ) ;
- if ( nscb.nextt == SPECIAL ) {
- if ( scratch [0] == '(' )
- parens++ ;
- else if ( scratch [0] == ')' )
- parens-- ;
- } ;
- } ;
- if ( parens == 0 && ! poundsign ) {
- SymbolLength = GetSymbol ( &nscb, InputLine, scratch,
- MAX_SYMBOL ) ;
- if ( nscb.nextt == SPECIAL && ( scratch [0] == ';' ||
- scratch [0] == ',' ) ) {
- strcpy ( symbol, scratch ) ;
- goto Retry1 ;
- } ;
- } ;
- } ;
- return ( TRUE ) ;
- } ;
- strcpy ( symbol, scratch ) ;
- goto Retry1 ;
- } ;
-
- if ( nscb.nextt == SPECIAL ) {
- if ( symbol [0] == '/' && InputLine [nscb.nextp] == '*' ) {
- Con:
- while ( InputLine [++nscb.nextp] != '*' )
- if ( InputLine [nscb.nextp] == '\0' ) {
- table = FGetLine ( InputFile, InputLine, 2*MAX_INPUT ) ;
- if ( table == EOF )
- return ( FALSE ) ;
- nscb.nextp = -1 ;
- } ;
- nscb.nextp++ ;
- if ( InputLine [nscb.nextp] != '/' ) {
- nscb.nextp-- ;
- goto Con ;
- } ;
- nscb.nextp++ ;
- }
- else if ( symbol [0] == '{' )
- nestlevel++ ;
- else if ( symbol [0] == '}' )
- nestlevel-- ;
- else if ( symbol [0] == '\"' ) {
- table = strlen ( InputLine ) ;
- Quoted:
- if ( InputLine [table-1] == '\\' ) {
- table = FGetLine ( InputFile, InputLine, 2*MAX_INPUT ) ;
- if ( table == EOF )
- return ( FALSE ) ;
- nscb.nextp = -1 ;
- while ( InputLine [++nscb.nextp] != '\"' &&
- InputLine [ nscb.nextp] != '\0' )
- ;
- if ( InputLine [nscb.nextp] == '\0' )
- goto Quoted ;
- } ;
- goto Retry ;
- } ;
- } ;
-
- if ( nscb.nextt == EOS ) {
- table = FGetLine (InputFile, InputLine, 2*MAX_INPUT) ;
- if ( table == EOF )
- return ( FALSE ) ;
- else {
- nscb.nextp = 0 ;
- goto Retry ;
- } ;
- } ;
- goto Retry ;
- }
-
- IsKeyword ( Symbol )
-
- char Symbol [] ; /* Symbol which is to be classified */
-
- /*
- +--------------------------------------------------+
- | |
- | This procedure will classify the Symbol as |
- | to whether it is a 'C' keyword or not. |
- | |
- +--------------------------------------------------+
- */
-
- {
- static KEYWORD Keywords [] = {
- 4, "auto" ,
- 5, "break" ,
- 4, "case" ,
- 5, "cdecl" ,
- 4, "char" ,
- 8, "continue" ,
- 7, "default" ,
- 6, "define" ,
- 7, "defined" ,
- 2, "do" ,
- 6, "double" ,
- 4, "else" ,
- 5, "endif" ,
- 6, "extern" ,
- 3, "far" ,
- 5, "float" ,
- 3, "for" ,
- 7, "fortran" ,
- 4, "goto" ,
- 4, "huge" ,
- 2, "if" ,
- 5, "ifdef" ,
- 6, "ifndef" ,
- 7, "include" ,
- 3, "int" ,
- 4, "line" ,
- 4, "long" ,
- 4, "near" ,
- 6, "pascal" ,
- 8, "register" ,
- 6, "return" ,
- 5, "short" ,
- 6, "static" ,
- 6, "struct" ,
- 6, "switch" ,
- 7, "typedef" ,
- 5, "undef" ,
- 5, "union" ,
- 8, "unsigned" ,
- 4, "void" ,
- 5, "while"
- } ;
- #define KeywordsLength ( sizeof (Keywords ) / sizeof (struct key_entry) )
-
- int SymbolLength ;
- int i ;
-
- SymbolLength = strlen ( Symbol ) ;
- for ( i = 0 ; i < KeywordsLength ; i++ )
- if ( SymbolLength == Keywords [i].length &&
- strcmp ( Symbol, Keywords [i].key ) == 0 )
- return ( TRUE ) ;
- return ( FALSE ) ;
- }
-
- IsLibraryCall ( Symbol )
-
- char Symbol [] ; /* Symbol which is to be classified */
-
- /*
- +--------------------------------------------------+
- | |
- | This procedure will classify the Symbol as |
- | to whether it is a 'C' libary routine or not. |
- | |
- +--------------------------------------------------+
- */
-
- {
- static KEYWORD Procwords [] = {
- 3, "abs" ,
- 5, "abort" ,
- 6, "access" ,
- 4, "acos" ,
- 7, "asctime" ,
- 4, "asin" ,
- 4, "atan" ,
- 5, "atan2" ,
- 4, "atof" ,
- 4, "atoi" ,
- 4, "atol" ,
- 4, "bdos" ,
- 6, "calloc" ,
- 5, "cgets" ,
- 5, "chdir" ,
- 5, "chmod" ,
- 6, "chsize" ,
- 8, "clearerr" ,
- 5, "close" ,
- 3, "cos" ,
- 4, "cosh" ,
- 7, "cprintf" ,
- 5, "cputs" ,
- 5, "creat" ,
- 6, "cscanf" ,
- 5, "ctime" ,
- 3, "eof" ,
- 4, "exit" ,
- 6, "fclose" ,
- 4, "feof" ,
- 5, "fgetc" ,
- 5, "fgets" ,
- 5, "fopen" ,
- 7, "fprintf" ,
- 5, "fputc" ,
- 5, "fputs" ,
- 6, "FP_OFF" ,
- 6, "FP_SEG" ,
- 5, "fread" ,
- 4, "free" ,
- 7, "freopen" ,
- 6, "fscanf" ,
- 5, "fseek" ,
- 5, "ftell" ,
- 5, "fwrite" ,
- 4, "gcvt" ,
- 7, "gdosint" ,
- 4, "getc" ,
- 4, "gets" ,
- 7, "isalpha" ,
- 7, "iscntrl" ,
- 7, "isdigit" ,
- 7, "isprint" ,
- 4, "itoa" ,
- 4, "ltoa" ,
- 6, "malloc" ,
- 3, "min" ,
- 6, "printf" ,
- 4, "putc" ,
- 5, "qsort" ,
- 6, "sizeof" ,
- 7, "sprintf" ,
- 6, "strcat" ,
- 6, "strcmp" ,
- 7, "strcmpi" ,
- 6, "strcpy" ,
- 6, "strlen" ,
- 7, "strncpy" ,
- 6, "strupr" ,
- 4, "time" ,
- 7, "toupper" ,
- 5, "write"
- } ;
- #define ProcwordsLength ( sizeof (Procwords) / sizeof (struct key_entry) )
-
- int SymbolLength ;
- int i ;
-
- SymbolLength = strlen ( Symbol ) ;
- for ( i = 0 ; i < ProcwordsLength ; i++ )
- if ( SymbolLength == Procwords [i].length &&
- strcmp ( Symbol, Procwords [i].key ) == 0 )
- return ( TRUE ) ;
- return ( FALSE ) ;
- }
-
- WORDNODEPTR AddToTree ( subtree, word, linenumber )
-
- WORDNODEPTR subtree ;
- char word [] ;
- int linenumber ;
-
-
- /*
- +--------------------------------------------------+
- | |
- | This procedure will attempt to place the word |
- | 'word' in the binary tree pointed to by |
- | 'subtree'. |
- | |
- +--------------------------------------------------+
- */
-
- {
- char *strsave () ;
- int cond ;
- LINENODEPTR ptr ;
-
-
- if ( subtree == NULL ) {
- if ( linenumber >= 0 )
- totalsymbols++ ;
- subtree = (WORDNODEPTR) malloc ( sizeof ( WORDNODE ) ) ;
- if ( subtree == NULL ) {
- printf ( "Out of memory." ) ;
- exit ( 1 ) ;
- } ;
- subtree->left = NULL ;
- subtree->right = NULL ;
- subtree->word = strsave ( word ) ;
- subtree->printpage = -1 ;
- calledprocedure = subtree->word ;
- if ( linenumber >= 0 ) {
- subtree->filename = filenames [nrfiles] ;
- entersegment ( CurrentSegment, subtree->word ) ;
- }
- else
- subtree->filename = NULL ;
- subtree->linenumber = linenumber ;
- subtree->firstlinenode = NULL ;
- subtree->lastlinenode = NULL ;
- }
- else if ( ( cond = strcmpi ( word, subtree->word ) ) == 0 &&
- ( cond = strcmp ( word, subtree->word ) ) == 0 ) {
- if ( subtree->filename != NULL && linenumber >= 0 ) {
- if ( ! poundsign ) {
- printf ( "Duplicate procedure definition --> %s\n", word ) ;
- printf (
- " Defined in %s on line %d and in %s on line %d\n" ,
- subtree->filename, subtree->linenumber, filenames [nrfiles],
- linenumber ) ;
- } ;
- } ;
-
- if ( linenumber >= 0 ) {
- totalsymbols++ ;
- subtree->filename = filenames [nrfiles] ;
- subtree->linenumber = linenumber ;
- entersegment ( CurrentSegment, subtree->word ) ;
- } ;
- calledprocedure = subtree->word ;
- }
- else if ( cond < 0 )
- subtree->left = AddToTree ( subtree->left , word, linenumber ) ;
- else
- subtree->right = AddToTree ( subtree->right, word, linenumber ) ;
-
- return ( subtree ) ;
- }
-
- addtree ( subtree, procedure, word )
-
- WORDNODEPTR subtree ;
- char procedure [] ;
- char word [] ;
-
- /*
- +--------------------------------------------------+
- | |
- | This procedure will attempt to place the word |
- | 'word' in the binary tree pointed to by |
- | 'subtree'. This is an inverted list from |
- | the tree maintained by AddToTree. |
- | |
- +--------------------------------------------------+
- */
-
- {
- char *strsave () ;
- int cond ;
- LINENODEPTR ptr ;
-
-
- if ( subtree != NULL ) {
- if ( ( cond = strcmpi ( procedure, subtree->word ) ) == 0 &&
- ( cond = strcmp ( procedure, subtree->word ) ) == 0 ) {
- ptr = (LINENODEPTR) malloc ( sizeof (LINENODE) ) ;
- if ( ptr == NULL ) {
- printf ( "Out of memory" ) ;
- exit ( 1 ) ;
- } ;
- ptr->procedure = calledprocedure ;
- ptr->nextlinenode = NULL ;
- if ( subtree->lastlinenode == NULL ) {
- subtree->firstlinenode = ptr ;
- subtree->lastlinenode = ptr ;
- }
- else {
- subtree->lastlinenode->nextlinenode = ptr ;
- subtree->lastlinenode = ptr ;
- } ;
- }
- else if ( cond < 0 )
- addtree ( subtree->left , procedure, word ) ;
- else
- addtree ( subtree->right, procedure, word ) ;
- } ;
-
- return ;
- }
-
- char *strsave ( word )
-
- char word [] ;
-
- /*
- +--------------------------------------------------+
- | |
- | This procedure allocates memory and saves |
- | 'word' in memory and returns a pointer to it. |
- | |
- +--------------------------------------------------+
- */
-
- {
- char *strloc ;
-
- if ( ( strloc = malloc ( strlen ( word ) + 1 ) ) == NULL ) {
- printf ( "Out of memory." ) ;
- exit ( 1 ) ;
- } ;
- strcpy ( strloc, word ) ;
- return ( strloc ) ;
- }
-
- checktree ( root, subtree, procedure )
-
- WORDNODEPTR root ;
- WORDNODEPTR subtree ;
- char procedure [] ;
-
- /*
- +--------------------------------------------------+
- | |
- | This procedure calls itself recursively to |
- | trace down all the procedures called by a |
- | given procedure to ensure that they are in the |
- | proper calling heirarchy. If they arn't, |
- | a trace back is performed indicating the |
- | errant calling heirarchy. |
- | |
- +--------------------------------------------------+
- */
-
- {
- int cond ;
-
- if ( subtree != NULL ) {
- if ( ( cond = strcmpi ( procedure, subtree->word ) ) == 0 &&
- ( cond = strcmp ( procedure, subtree->word ) ) == 0 ) {
- if ( ! checkentry ( root, subtree ) ) {
- strcpy ( InputLine, margin ) ;
- strcat ( InputLine, margin ) ;
- strcat ( InputLine, "--> " ) ;
- strcat ( InputLine, procedure ) ;
- if ( subtree->filename != NULL ) {
- strcat ( InputLine, " (" ) ;
- strcat ( InputLine, subtree->filename ) ;
- strcat ( InputLine, ")" ) ;
- }
- else
- strcat ( InputLine, " (????)" ) ;
- printline ( InputLine ) ;
- return ( FALSE ) ;
- } ;
- }
- else if ( cond < 0 )
- return ( checktree ( root, subtree->left , procedure ) ) ;
- else
- return ( checktree ( root, subtree->right, procedure ) ) ;
- } ;
-
- return ( TRUE ) ;
- }
-
- checkentry ( root, tree )
-
- WORDNODEPTR root ;
- WORDNODEPTR tree ;
-
- /*
- +--------------------------------------------------+
- | |
- | This procedure checks the current procedure |
- | to see if it is in the proper calling |
- | heirarchy. If it isn't, a trace back is |
- | performed indicating the errant calling |
- | sequence. If it is, a trace is performed |
- | on all procedures called by this procedure. |
- | |
- +--------------------------------------------------+
- */
-
- {
- LINENODEPTR lptr ;
- LINENODEPTR sort [150 ] ;
- int nrrefs ;
- int pos ;
- int i ;
- char *itoa () ;
- char *last ;
- int currentlevel ;
- static char nullstring [1] = { "" } ;
-
- if ( nestlevel > maxlevel ) /* If at max. nesting level, return */
- return ;
-
- /* Check if procedure is in current segment or root */
-
- currentlevel = nestlevel ;
- if ( tree->filename != NULL &&
- ! insegment ( CurrentSegment, tree->word ) &&
- ! insegment ( 0 , tree->word ) ) {
- strcpy ( InputLine, margin ) ;
- strcat ( InputLine, tree->word ) ;
- if ( tree->filename != NULL ) {
- strcat ( InputLine, " (" ) ;
- strcat ( InputLine, tree->filename ) ;
- strcat ( InputLine, ")" ) ;
- }
- else
- strcat ( InputLine, " (????)" ) ;
- strcat ( InputLine, " not in calling heirarchy." ) ;
- printline ( "" ) ;
- printline ( InputLine ) ;
-
- return ( FALSE ) ;
- } ;
-
- /* Perform check on all called procedures. */
- /* First gather up procedures called and sort them. */
-
- lptr = tree->firstlinenode ;
- nrrefs = 0 ;
- while ( lptr != NULL ) {
- pos = FALSE ;
- for ( i = 0 ; i < nrrefs ; i++ )
- if ( strcmpi ( lptr->procedure, sort [i]->procedure ) == 0 ) {
- pos = TRUE ;
- break ;
- } ;
- if ( ! pos ) {
- sort [nrrefs++] = lptr ;
- if ( nrrefs >= 150 ) {
- printf ("Too many procedure calls in %s. List truncated to 150.\n",
- tree->word ) ;
- break ;
- } ;
- } ;
- lptr = lptr->nextlinenode ;
- } ;
-
- /* Sort the CALLS to avoid duplicate processing */
-
- qsort ( sort, nrrefs, sizeof (LINENODEPTR), Compare ) ;
-
- /* Invoke checktree recursively */
-
- lptr = sort [0] ;
- last = nullstring ;
- pos = 0 ;
- nestlevel++ ;
- while ( pos < nrrefs ) {
- if ( strcmpi ( last, lptr->procedure ) != 0 ) {
- if ( ! checktree ( root, root, lptr->procedure ) )
- return ( FALSE ) ;
- } ;
- last = lptr->procedure ;
- lptr = sort [++pos] ;
- } ;
- nestlevel-- ;
- return ( TRUE ) ;
- }
-
- Compare ( key1, key2 )
-
- LINENODEPTR key1 [] ;
- LINENODEPTR key2 [] ;
-
- /*
- +--------------------------------------------------+
- | |
- | This procedure is the compare procedure used |
- | to sort procedure names. |
- | |
- +--------------------------------------------------+
- */
-
- {
- return ( strcmpi ( key1[0]->procedure, key2[0]->procedure ) ) ;
- }
-
- printline ( line )
-
- char line [] ;
-
- /*
- +--------------------------------------------------+
- | |
- | This procedure will print a line to the output |
- | file. If the number of lines printed exceeds |
- | the page length, a page eject with header info |
- | is printed. |
- | |
- +--------------------------------------------------+
- */
-
- {
- int i ;
-
- if ( ++OutputLineNumber > 60 ) {
- OutputPage++ ;
- fprintf ( OutputFile, "\f\n\n\n CHKSEG for %s %s",
- fulltemplate, datetime ) ;
- for ( i = strlen ( fulltemplate ) + 41 ;
- i < 70 ; i++ )
- fprintf ( OutputFile, " " ) ;
- fprintf ( OutputFile, "Page %d\n\n", OutputPage ) ;
- OutputLineNumber = 6 ;
- } ;
-
- fprintf ( OutputFile, "%s\n", line ) ;
- }
-
- GetSymbol ( nptr, string, symbol, maxsym )
-
- NSCBPTR nptr ; /* GetSymbol control block pointer */
- char string[ ] ; /* string to scan for symbol */
- char symbol[ ] ; /* symbol returned */
- int maxsym ; /* maximum symbol length to return */
-
- /*+-------------------------------------------------------------------------+
- ! !
- ! !
- ! PURPOSE: !
- ! !
- ! This procedure will return the next symbol in the input !
- ! character string 'string'. Values of where to start scanning !
- ! for the next symbol, etc., are contained in the NSCB !
- ! control block pointed to by 'nptr'. !
- ! !
- ! GetSymbol is invoked as follows: !
- ! !
- ! symlc = GetSymbol ( &nscb, string, symbol, maxsym ) ; !
- ! !
- ! where the value returned (symlc) is the symbol length in chars. !
- ! The length of the symbol (symlc) does not include a zero byte !
- ! which terminates the symbol. This zero byte is accounted for in !
- ! the maximum symbol length which can be returned -- consequently, !
- ! a maximum symbol of maxsym-1 will be returned. !
- ! !
- ! PARAMETERS: !
- ! !
- ! &nscb - Pointer to a NSCB control block. !
- ! string - Character string which is to be scanned for !
- ! the next symbol. !
- ! symbol - Character variable in which the the returned !
- ! symbol will be placed. !
- ! maxsym - Maximum number of characters to return in !
- ! symbol. !
- ! NOTES: !
- ! !
- ! For each call to GetSymbol, the next symbol is returned !
- ! with a classification as to the type of symbol. Types of !
- ! symbols parsed by this scanner are: !
- ! !
- ! IDENTIFIERS LITERALS INTEGERS !
- ! FLOAT SPECIAL EOS !
- ! OTHER !
- ! !
- ! For the purposes of the above definitions, an identifier !
- ! begins with an alphabetic character and may contain alphabetic !
- ! or numeric characters. Additionally, for literals, the !
- ! characters enclosed in the quote marks (either " or ') are !
- ! returned without the enclosing quotes. A double quote within !
- ! a literal will cause a single quote to be returned within the !
- ! literal (e.g., 'Tom''s House' --> Tom's House). !
- ! !
- ! The value for nptr->nextp must be set to the appropriate !
- ! starting position in 'string' before the first call to !
- ! GetSymbol. It must also be reset after an end of string !
- ! has been encountered. !
- ! !
- ! If 'maxsym' is less than or equal to one , no textual !
- ! symbol will be returned. However, if the symbol is !
- ! an integer or a floating point number, the value will be !
- ! decoded appropriately and the type of symbol will be set. !
- ! !
- ! !
- +-------------------------------------------------------------------------+*/
-
- {
- int save_position, symlc , n, i ;
- char quote ;
-
- /*-------------------------------------------------------------*/
- /* Initialize Parameters */
- /*-------------------------------------------------------------*/
-
- if ( nptr->nextp < 0 ) nptr->nextp = 0 ;
- if ( --maxsym < 0 ) maxsym = 0 ;
- symlc = 0 ;
-
- /*-------------------------------------------------------------*/
- /* Skip leading blanks */
- /*-------------------------------------------------------------*/
-
- while ( string[nptr->nextp] != '\0' && isspace (string[nptr->nextp]) )
- nptr->nextp++ ;
-
- /*-------------------------------------------------------------*/
- /* Set start of symbol in nptr->nextc */
- /*-------------------------------------------------------------*/
-
- nptr->nextc = nptr->nextp ;
- if ( string[nptr->nextc] == '\0' ) {
- nptr->nextt = EOS ; /* EOS found */
- if ( maxsym > 0 ) symbol[0] = '\0' ;
- return ( 0 ) ;
- } ;
-
- /*-------------------------------------------------------------*/
- /* Build symbol based on the first character encountered */
- /*-------------------------------------------------------------*/
-
- if ( isalpha ( string[nptr->nextp] ) ) { /* Identifier */
- nptr->nextt = IDENTIFIER ;
- for ( ++nptr->nextp ; string[nptr->nextp] != '\0' &&
- ( isalpha ( string[nptr->nextp] ) ||
- isdigit ( string[nptr->nextp] ) ||
- string[nptr->nextp] == '\'' ||
- string[nptr->nextp] == '_' )
- ; nptr->nextp++ ) ;
- }
- else if ( isdigit ( string[nptr->nextp] ) ) { /* Integer */
- nptr->nextt = INTEGER ;
-
- StillInteger:
- for ( ++nptr->nextp ; string[nptr->nextp] != '\0' &&
- isdigit ( string[nptr->nextp] ) ; nptr->nextp++ ) ;
- if ( string[nptr->nextp] == ',' && isdigit ( string[nptr->nextp+1]))
- goto StillInteger ;
- if ( string[nptr->nextp] == '.' ) {
-
- IsFloat:
- nptr->nextt = FLOAT ; /* Floating pt. */
- for ( ++nptr->nextp ; string[nptr->nextp] != '\0' &&
- isdigit ( string[nptr->nextp] ) ; nptr->nextp++ ) ;
- } ;
- if ( isalpha (string[nptr->nextp]) || string[nptr->nextp] == '\'') {
- nptr->nextt = OTHER ;
- for ( ++nptr->nextp ; string[nptr->nextp] != '\0' &&
- ( isdigit ( string[nptr->nextp] ) ||
- isalpha ( string[nptr->nextp] ) ||
- string[nptr->nextp] == '.' ||
- string[nptr->nextp] == '\'' ) ; nptr->nextp++ ) ;
- } ;
- if ( string[nptr->nextp-1] == '.' ) { /* If '.' is last, */
- nptr->nextp-- ; /* assume it is period */
- if ( nptr->nextt == FLOAT )
- nptr->nextt = INTEGER ;
- } ;
- }
- else if (( string[nptr->nextp] == '"' ) ||
- ( string[nptr->nextp] == '\'') ) { /* Literal maybe */
- nptr->nextt = SPECIAL ;
- quote = string[nptr->nextp] ;
- save_position = nptr->nextc + 1 ;
-
- loop:
- for ( ++nptr->nextp ; string[nptr->nextp] != '\0' &&
- string[nptr->nextp] != quote ; nptr->nextp++ ) ;
- if ( string[nptr->nextp] == '\0' )
- nptr->nextp = save_position ; /* Unpaired " ' */
- else {
- nptr->nextt = LITERAL ; /* Literal */
- n = nptr->nextp - save_position ;
- if ( ( symlc + n ) > maxsym ) n = maxsym - symlc ;
- for ( ; n > 0 ; n-- )
- symbol[symlc++] = string[save_position++] ;
- save_position = ++nptr->nextp ;
- if (string[nptr->nextp] == quote)
- goto loop ;
- }
- }
- else { /* Special char.*/
- if ( string[nptr->nextp] == '.' &&
- isdigit ( string[nptr->nextp+1] ) )
- goto IsFloat ;
- else {
- nptr->nextt = SPECIAL ;
- nptr->nextp++ ;
- }
- }
-
- /*-------------------------------------------------------------*/
- /* Set symbol to return if not already set */
- /*-------------------------------------------------------------*/
-
- if ( nptr->nextt != LITERAL ) {
- symlc = nptr->nextp - nptr->nextc ;
- if ( symlc > maxsym ) symlc = maxsym ;
- i = nptr->nextc ;
- n = 0 ;
- while ( i < nptr->nextp )
- symbol[n++] = string[i++] ;
- }
-
- /*-------------------------------------------------------------*/
- /* Terminate symbol with a 0 byte. */
- /*-------------------------------------------------------------*/
-
- if ( symlc > 0 ) symbol[symlc] = '\0' ;
- return ( symlc ) ; /* Return the symbol length */
- }
-
-
- GetFileSegments ()
-
- /*
- +--------------------------------------------------+
- | |
- | This procedure prompts the user for the path |
- | name of the file which contains the MSC |
- | segment link directives. It then load the |
- | information into internal arrays for later |
- | processing. |
- | |
- +--------------------------------------------------+
- */
-
- {
- char symbol [MAX_SYMBOL+1] ;
- char lastsymbol [MAX_SYMBOL+1] ;
- int lasttype ;
- int highsegment ;
- int cursegment ;
- int done ;
-
- highsegment = 0 ;
- cursegment = 0 ;
- lasttype = 0 ;
- done = FALSE ;
-
- while ( ! done ) {
- printf ("Enter path name of file containing segment specification\n" ) ;
- printf ( ">>> " ) ;
- if ( FGetLine ( stdin, InputFileName, MAXPATH ) > 0 ) {
- if ((InputFile = fopen ( InputFileName, "r" )) == NULL ) {
- printf ( "Unable to open file %s\n", InputFileName ) ;
- continue ;
- } ;
- while ( ! done ) {
- if ( FGetLine ( InputFile, InputLine, 4*MAX_INPUT ) == EOF )
- break ;
- strupr ( InputLine ) ;
- nscb.nextp = 0 ;
- nscb.nextt = 0 ;
- while ( nscb.nextt != EOS ) {
- GetSymbol ( &nscb, InputLine, symbol, MAX_SYMBOL+1 ) ;
- if ( nscb.nextt == SPECIAL ) {
- if ( symbol [0] == '(' ) {
- cursegment = highsegment + 1 ;
- highsegment = cursegment ;
- }
- else if ( symbol [0] == '+' || symbol [0] == ')' ) {
- if ( lasttype == IDENTIFIER ) {
- FileSegs [NoOfFileSegs ].filename =
- strsave (lastsymbol) ;
- FileSegs [NoOfFileSegs++].filesegno= cursegment ;
- } ;
- if ( symbol [0] == ')' )
- cursegment = 0 ;
- } ;
- }
- else if ( nscb.nextt == EOS && lastsymbol [0] != '+' ) {
- if ( lasttype == IDENTIFIER ) {
- FileSegs [NoOfFileSegs ].filename =
- strsave ( lastsymbol ) ;
- FileSegs [NoOfFileSegs++].filesegno = cursegment ;
- } ;
- done = TRUE ;
- break ;
- } ;
- strcpy ( lastsymbol, symbol ) ;
- lasttype = nscb.nextt ;
- if ( lasttype == IDENTIFIER )
- strcat ( lastsymbol, ".C" ) ;
- } ;
- } ;
- }
- else
- return ( FALSE ) ;
- printf (
- "*** Loaded %d object file specifications for root and %d segments\n",
- NoOfFileSegs, highsegment ) ;
- } ;
- return ( TRUE ) ;
- }
-
- SetSegmentNumber ( filename )
-
- char filename [] ;
-
- /*
- +--------------------------------------------------+
- | |
- | This procedure looks up the procedure name |
- | passed and sets 'CurrentSegment' to the |
- | segment number in which the procedure was |
- | found. If the procedure was not found in |
- | any segment, it is assumed to be in the root. |
- | |
- +--------------------------------------------------+
- */
-
- {
- int i ;
-
- for ( i = 0 ; i < NoOfFileSegs ; i++ )
- if ( stricmp ( FileSegs [i].filename, filename ) == 0 ) {
- CurrentSegment = FileSegs [i].filesegno ;
- return ;
- } ;
- CurrentSegment = 0 ;
- }
-
- entersegment ( SegmentNo, ProcStringPtr )
-
- int SegmentNo ;
- char *ProcStringPtr ;
-
- /*
- +--------------------------------------------------+
- | |
- | This procedure adds a given procedure name |
- | to the linked list maintained for each |
- | segment number (including the root). |
- | |
- +--------------------------------------------------+
- */
-
- {
- LINENODEPTR sptr ;
-
- if ( Segments [SegmentNo].procedure == NULL )
- Segments [SegmentNo].procedure = ProcStringPtr ;
- else {
- sptr = &Segments [SegmentNo] ;
- while ( sptr->nextlinenode != NULL )
- if ( stricmp ( sptr->procedure, ProcStringPtr ) == 0 )
- return ;
- else
- sptr = sptr->nextlinenode ;
- if ( stricmp ( sptr->procedure, ProcStringPtr ) == 0 )
- return ;
- sptr->nextlinenode = (LINENODEPTR) malloc ( sizeof (LINENODE) ) ;
- if ( sptr->nextlinenode == (LINENODEPTR) NULL ) {
- printf ( "Out of memory" ) ;
- exit ( 1 ) ;
- } ;
- sptr = sptr->nextlinenode ;
- sptr->procedure = ProcStringPtr ;
- sptr->nextlinenode = (LINENODEPTR) NULL ;
- } ;
- }
-
- insegment ( segno, procedure )
-
- int segno ;
- char procedure [] ;
-
- /*
- +--------------------------------------------------+
- | |
- | This procedure looks up the procedure name |
- | passed to see if it is in the segment number |
- | passed. If it is, a value of TRUE is returned.|
- | Otherwise, FALSE. |
- | |
- +--------------------------------------------------+
- */
- {
- LINENODEPTR sptr ;
-
- sptr = (LINENODEPTR) &Segments [segno] ;
- while ( sptr != (LINENODEPTR) NULL )
- if ( stricmp (sptr->procedure, procedure ) == 0 )
- return ( TRUE ) ;
- else
- sptr = sptr->nextlinenode ;
- return ( FALSE ) ;
- }